#include "stdafx.h"
#include "FlashView.h"

using namespace ShockwaveFlashObjects;

FlashView::FlashView()
:m_pSite(0)
,m_dwLS(0)
,m_dwMS(0)
,m_bInvailRect(false)
{

}

FlashView::~FlashView()
{
	if (m_flashObj)
		m_flashObj->Stop();

	if (m_pSite)
		m_pSite->Release();

	if (m_oleObj)
		m_oleObj->Close(OLECLOSE_NOSAVE);

}

bool FlashView::LoadMovie( const wchar_t *pFile )
{
	if (!m_flashObj) {

		if (!FlashVerCheck())
			return false;

		m_pSite = new FlashSite(this);
		m_pSite->AddRef();

		CLSID clsid = {0xD27CDB6E, 0xAE6D, 0x11cf, 0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0, 0};
		if (FAILED(CLSIDFromProgID(L"ShockwaveFlash.ShockwaveFlash", &clsid))) {
			return false;
		}

		HRESULT result = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, IID_IOleObject, (void**)&m_oleObj);
		if (FAILED(result) || (!m_oleObj)) {
			return false;
		}

		CComQIPtr<IShockwaveFlash> flashObj = m_oleObj;
		m_flashObj = flashObj;
		CComQIPtr<IOleInPlaceObjectWindowless> windowlessObj = m_oleObj;
		m_windowlessObj = windowlessObj;

		if (!m_flashObj)
			return false;

		if ((m_dwMS >= 0x000a0001 && m_dwLS >= 0x00350000) || m_dwMS >= 0x000b0000)
			m_pSite->SetTimerService(FALSE);
		else
			m_pSite->SetTimerService(TRUE);
		
		m_oleObj->SetClientSite(m_pSite);

		//CComBSTR bsWMode = L"opaque";
		CComBSTR bsWMode = L"transparent";
		m_flashObj->put_WMode(bsWMode);

		SIZE szFlash = {0};
		GetSize(&szFlash);
		CComQIPtr<IOleInPlaceObject> oleInPlaceObj = m_oleObj;
		RECT rc = {0, 0, szFlash.cx, szFlash.cy};
		oleInPlaceObj->SetObjectRects(&rc, &rc);
		m_oleObj->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, m_pSite, -1, 0, &rc);
	}

	if (m_flashObj) {
		m_flashObj->put_Movie(CComBSTR(pFile));
	}

	return true;
}

void FlashView::Render( HDC hdc, const RECT *lpRect )
{
	if (m_bInvailRect)
		return;

	CComQIPtr<IViewObjectEx> pView = m_flashObj;
	
	RECT rcFlash = {0};
	GetRect(&rcFlash);

	::OleDraw(pView, DVASPECT_OPAQUE, hdc, &rcFlash);
}

BOOL FlashView::FlashVerCheck()
{
	DWORD dwMS = 0;
	DWORD dwLS = 0;

	LONG retVal;

	TCHAR strPath[MAX_PATH]; //flash.ocx pathname
	HKEY clsKey;
	retVal = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_QUERY_VALUE, &clsKey);
	if (retVal != ERROR_SUCCESS)
	{
		return FALSE;
	}
	else 
	{
		HKEY idKey;
		TCHAR strID[100] = _T("{D27CDB6E-AE6D-11cf-96B8-444553540000}"); //falsh.ocx
		retVal = ::RegOpenKeyEx(clsKey, strID, 0, KEY_QUERY_VALUE,&idKey);
		if(retVal != ERROR_SUCCESS)
		{
			RegCloseKey(clsKey);
			return FALSE;
		}
		else
		{
			//HKEY_CLASSES_ROOT\CLSID\{D27CDB70-AE6D-11cf-96B8-444553540000}\InprocServer32
			TCHAR childKey[30] = _T("InprocServer32");
			GetRegKey(idKey, childKey, strPath);
		}

		RegCloseKey(idKey);
	}

	RegCloseKey(clsKey);

	if(!GetFileVersion(strPath, dwMS, dwLS))
	{
		return FALSE;
	}

	m_dwMS = dwMS;
	m_dwLS = dwLS;

	if (dwMS >= 0x80000)
	{
		return TRUE;
	}

	return FALSE;
}

BOOL FlashView::GetFileVersion(LPCTSTR szFileName, DWORD &dwMS, DWORD &dwLS)
{
	LPBYTE  lpVersionData; 
	DWORD dwHandle;     
	DWORD dwDataSize = ::GetFileVersionInfoSize((LPTSTR)szFileName, &dwHandle); 
	if ( dwDataSize == 0 ) 
	{       
		return FALSE;
	}

	lpVersionData = new BYTE[dwDataSize]; 
	if (!::GetFileVersionInfo((LPTSTR)szFileName, dwHandle, dwDataSize, (LPVOID)lpVersionData) )
	{
		delete[] lpVersionData;
		return FALSE;
	}

	UINT nQuerySize;
	VS_FIXEDFILEINFO* pVsffi = NULL;
	if (::VerQueryValue((void*)lpVersionData, _T("\\"),
		(void**)&pVsffi, &nQuerySize) )
	{
		dwMS = pVsffi->dwFileVersionMS;
		dwLS = pVsffi->dwFileVersionLS;		 
		delete [] lpVersionData;    
		return TRUE;
	}

	delete [] lpVersionData;
	return FALSE;
}

LONG FlashView::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
	HKEY hkey;
	LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);

	if (retval == ERROR_SUCCESS) 
	{
		long datasize = MAX_PATH;
		TCHAR data[MAX_PATH];
		RegQueryValue(hkey, NULL, data, &datasize);
		lstrcpyn(retdata,data,MAX_PATH);
		RegCloseKey(hkey);
	}

	return retval;
}

void FlashView::Update(LPCRECT pRect)
{
	if (!m_bInvailRect)
		InvalidateRect(pRect);
}